/*
 *
 *      Copyright (c) 2018-2025, kexingcp All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: kexingcp
 *
 */

package com.evaluation.kexingcp.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.evaluation.kexingcp.admin.api.dto.UserDTO;
import com.evaluation.kexingcp.admin.api.dto.UserInfo;
import com.evaluation.kexingcp.admin.api.entity.SysDept;
import com.evaluation.kexingcp.admin.api.entity.SysTenant;
import com.evaluation.kexingcp.admin.api.entity.SysUser;
import com.evaluation.kexingcp.admin.api.vo.UserExcelVO;
import com.evaluation.kexingcp.admin.api.vo.UserVO;
import com.evaluation.kexingcp.admin.service.SysDeptService;
import com.evaluation.kexingcp.admin.service.SysTenantService;
import com.evaluation.kexingcp.admin.service.SysUserService;
import com.evaluation.kexingcp.common.core.constant.CommonConstants;
import com.evaluation.kexingcp.common.core.exception.ErrorCodes;
import com.evaluation.kexingcp.common.core.util.MsgUtils;
import com.evaluation.kexingcp.common.core.util.R;
import com.evaluation.kexingcp.common.data.tenant.TenantContextHolder;
import com.evaluation.kexingcp.common.excel.annotation.RequestExcel;
import com.evaluation.kexingcp.common.log.annotation.SysLog;
import com.evaluation.kexingcp.common.security.annotation.HasPermission;
import com.evaluation.kexingcp.common.security.annotation.Inner;
import com.evaluation.kexingcp.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.usermodel.*;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author kexingcp
 * @date 2018/12/16
 */
@RestController
@AllArgsConstructor
@RequestMapping("/user")
@Tag(description = "user", name = "用户管理模块")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysUserController {

    private final SysUserService userService;
    private final SysTenantService tenantService;
    private final SysDeptService deptService;

    /**
     * 获取指定用户全部信息
     *
     * @return 用户信息
     */
    @Inner
    @GetMapping("/info/{username}")
    public R info(@PathVariable String username) {
        List<SysTenant> tenants = tenantService.getNormalTenant()
                .stream()
                .filter(tenant -> tenant.getStartTime().isBefore(LocalDateTime.now()))
                .filter(tenant -> tenant.getEndTime().isAfter(LocalDateTime.now()))
                .filter(tenant -> tenant.getId().equals(TenantContextHolder.getTenantId()))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(tenants)) {
            return R.failed("账号已过期,请联系管理员续费");
        }


        // 修改菜单状态

        SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
        if (user == null) {
            return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERINFO_EMPTY, username));
        }
        return R.ok(userService.findUserInfo(user));
    }

    /**
     * 获取当前用户全部信息
     *
     * @return 用户信息
     */
    @GetMapping(value = {"/info"})
    public R info() {
        String username = SecurityUtils.getUser().getUsername();
        SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
        if (user == null) {
            return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_QUERY_ERROR));
        }

        // UserInfo 是复用对象，不能通过设置 @jsonIgnore 来忽略密码字段
        UserInfo userInfo = userService.findUserInfo(user);
        userInfo.getSysUser().setPassword(null);
        return R.ok(userInfo);
    }

    /**
     * 通过ID查询用户信息
     *
     * @param id ID
     * @return 用户信息
     */
    @GetMapping("/details/{id}")
    public R user(@PathVariable Long id) {
        return R.ok(userService.selectUserVoById(id));
    }

    /**
     * 查询用户信息
     *
     * @param query 查询条件
     * @return 不为空返回用户名
     */
    @Inner(value = false)
    @GetMapping("/details")
    public R getDetails(@ParameterObject SysUser query) {
        SysUser sysUser = userService.getOne(Wrappers.query(query), false);
        return R.ok(sysUser == null ? null : CommonConstants.SUCCESS);
    }

    /**
     * 删除用户信息
     *
     * @param ids ID
     * @return R
     */
    @SysLog("删除用户信息")
    @DeleteMapping
    @HasPermission("sys_user_del")
    @Operation(summary = "删除用户", description = "根据ID删除用户")
    public R userDel(@RequestBody Long[] ids) {
        return R.ok(userService.deleteUserByIds(ids));
    }

    /**
     * 添加用户
     *
     * @param userDto 用户信息
     * @return success/false
     */
    @SysLog("添加用户")
    @PostMapping
    @HasPermission("sys_user_add")
    public R user(@RequestBody UserDTO userDto) {
        return R.ok(userService.saveUser(userDto));
    }

    /**
     * 分页查询用户
     *
     * @param page    参数集
     * @param userDTO 查询参数列表
     * @return 用户集合
     */
    @GetMapping("/page")
    public R getUserPage(@ParameterObject Page page, @ParameterObject UserDTO userDTO) {
        IPage<UserVO> pageResult = (IPage<UserVO>) userService.getUsersWithRolePage(page, userDTO);
        pageResult.convert(userVO -> {
            SysDept currentDept = deptService.getById(userVO.getDeptId());
            if (currentDept != null) {
                SysDept parentDept = deptService.getById(currentDept.getParentId());
                if (parentDept != null && parentDept.getParentId() != 0) {
                    userVO.setGradeName(parentDept.getName());
                }
            }

            return userVO;
        });
        return R.ok(pageResult);
    }

    /**
     * 管理员更新用户信息
     *
     * @param userDto 用户信息
     * @return R
     */
    @SysLog("更新用户信息")
    @PutMapping
    @HasPermission("sys_user_edit")
    public R updateUser(@Valid @RequestBody UserDTO userDto) {
        return R.ok(userService.updateUser(userDto));
    }

    /**
     * 修改个人信息 （当前用户）
     *
     * @param userDto userDto
     * @return success/false
     */
    @SysLog("修改个人信息")
    @PutMapping("/personal/edit")
    public R updateUserInfo(@Valid @RequestBody UserDTO userDto) {
        return userService.updateUserInfo(userDto);
    }

    /**
     * 修改个人密码 （当前用户）
     *
     * @param userDto 用户DTO对象，包含需要修改密码的用户信息
     * @return R 返回结果对象，包含修改密码操作的结果信息
     */
    @PutMapping("/personal/password")
    public R updatePassword(@RequestBody UserDTO userDto) {
        String username = SecurityUtils.getUser().getUsername();
        userDto.setUsername(username);
        return userService.changePassword(userDto);
    }

    /**
     * @param username 用户名称
     * @return 上级部门用户列表
     */
    @GetMapping("/ancestor/{username}")
    public R listAncestorUsers(@PathVariable String username) {
        return R.ok(userService.listAncestorUsers(username));
    }

    /**
     * 导出excel 表格
     *
     * @param userDTO 查询条件
     * @return
     */
//    @ResponseExcel
//    @GetMapping("/export")
//    @HasPermission("sys_user_export")
//    public List export(UserDTO userDTO, Long[] ids) {
//        return userService.listUser(userDTO, ids);
//    }

    /**
     * 导入用户
     *
     * @param excelVOList   用户列表
     * @param bindingResult 错误信息列表
     * @return R
     */
    @PostMapping("/import")
    @HasPermission("sys_user_export")
    public R importUser(@RequestExcel List<UserExcelVO> excelVOList, BindingResult bindingResult) {
        return userService.importUser(excelVOList, bindingResult, tenantService.getTenantConfig(), tenantService.getById(TenantContextHolder.getTenantId()));
    }

    /**
     * 锁定指定用户
     *
     * @param username 用户名
     * @return R
     */
    @Inner
    @PutMapping("/lock/{username}")
    public R lockUser(@PathVariable String username) {
        return userService.lockUser(username);
    }

    /**
     * 解绑定接口
     *
     * @param type 需要解绑定的类型
     * @return R 返回结果对象，包含解绑定操作的结果信息
     */
    @PostMapping("/unbinding")
    public R unbinding(String type) {
        return userService.unbinding(type);
    }

    /**
     * 校验密码接口
     *
     * @param password 需要校验的密码
     * @return R 返回结果对象，包含校验密码操作的结果信息
     */
    @PostMapping("/check")
    public R check(String password) {
        return userService.checkPassword(SecurityUtils.getUser().getUsername(), password);
    }

    /**
     * 根据角色ID列表获取用户ID列表接口
     *
     * @param roleIdList 角色ID列表
     * @return R 返回结果对象，包含根据角色ID列表获取到的用户ID列表信息
     */
    @GetMapping("/getUserIdListByRoleIdList")
    public R<List<Long>> getUserIdListByRoleIdList(Long[] roleIdList) {
        return R.ok(userService.listUserIdByRoleIds(CollUtil.toList(roleIdList)));
    }

    @GetMapping("/getUserListByRoleTeacher")
    public R<List<SysUser>> getUserIdListByRoleIdList() {
        return R.ok(userService.listUserIdByRoleName("TEACHER"));
    }

    /**
     * 根据部门ID列表获取用户ID列表接口
     *
     * @param deptIdList 部门ID列表
     * @return R 返回结果对象，包含根据部门ID列表获取到的用户ID列表信息
     */
    @GetMapping("/getUserIdListByDeptIdList")
    public R<List<SysUser>> getUserIdListByDeptIdList(Long[] deptIdList) {
        return R.ok(userService.listUserIdByDeptIds(CollUtil.toList(deptIdList)));
    }

    /**
     * 根据用户名获取用户列表
     *
     * @param username 用户名
     * @return 用户列表
     */
    @GetMapping("/getUserListByUserName")
    public R<List<SysUser>> getUserListByUserName(String username) {
        return R.ok(userService.list(Wrappers.<SysUser>lambdaQuery().like(SysUser::getUsername, username)));
    }

    /**
     * 根据IDS获取用户列表
     *
     * @param userIds ID列表
     * @return 用户列表
     */
    @GetMapping("/list")
    public R<List<SysUser>> getUserListByIds(@RequestParam("userIds") List<Long> userIds) {
        return R.ok(userService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId, userIds)));
    }

    /**
     * 返回excel模版
     */
    @GetMapping("/templateDownload")
    public void localFile(HttpServletResponse response) throws IOException {
        List<String> title = new ArrayList<>(List.of("用户名", "姓名", "年龄", "学历(小学,初中,高中,中专,大专,本科,硕士,博士)", "性别(男,女,未知)", "职业(教师,公务员,企业员工,学生,家长,农民,军人,干部,工人,知识分子,其他)", "昵称", "手机号"));

        Long tenantId = SecurityUtils.getUser().getTenantId();
        SysTenant tenant = tenantService.getById(tenantId);

        // , "邮箱", "部门名称", "岗位名称", "角色", "锁定标记(0:正常,9:已锁定)"
        if (tenant.getOrgType().equalsIgnoreCase("中小学")) {
            title.add("年级名称");
            title.add("班级名称");
        } else {
            title.add("邮箱");
            title.add("部门名称");
        }

        if (tenant != null && StrUtil.isNotBlank(tenant.getUserFields())) {
            JSONArray jsonArray = JSON.parseArray(tenant.getUserFields());
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                if (jsonObject.getBoolean("stateData")) {
                    String filedName = jsonObject.getString("fieldName");
                    if (filedName.contains("独生子女")) {
                        title.add("独生子女(是,否)");
                    } else if (filedName.contains("陪伴")) {
                        title.add("陪伴情况(父母一方陪伴,留守儿童,父母双方陪伴)");
                    } else if (filedName.contains("父母婚姻")) {
                        title.add("父母婚姻(正常,再婚,单亲,离异)");
                    } else if (filedName.contains("婚姻情况")) {
                        title.add("婚姻情况(未婚、已婚、丧偶、再婚)");
                    } else title.add(jsonObject.getString("fieldName"));
                }
            }
        }

        XSSFWorkbook workbook = new XSSFWorkbook();
        //创建工作表sheet
        XSSFSheet sheet = workbook.createSheet();
        //创建第一行
        XSSFRow row = sheet.createRow(0);
        row.setHeightInPoints(30);

        XSSFCell cell = null;
        //插入第一行的表头
        for (int i = 0; i < title.size(); i++) {
            cell = row.createCell(i);
            cell.setCellValue(title.get(i));

            XSSFCellStyle cellStyle = workbook.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
            cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
            cellStyle.setBorderTop(BorderStyle.THIN);//上边框
            cellStyle.setBorderRight(BorderStyle.THIN);//右边框
            cellStyle.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index);
            cellStyle.setWrapText(true);
            XSSFFont font = workbook.createFont();
            font.setBold(true);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            sheet.setColumnWidth(i, 10 * 256);
        }

        workbook.write(response.getOutputStream());
    }

    @GetMapping("/export")
    @PreAuthorize("@pms.hasPermission('sys_user_export')")
    public void userExport(HttpServletResponse response, UserDTO userDTO, Long[] ids) throws IOException {
        List<String> title = new ArrayList<>(List.of("用户名", "姓名", "年龄", "学历(小学,初中,高中,中专,大专,本科,硕士,博士)", "性别(男,女,未知)", "职业(教师,公务员,企业员工,学生,家长,农民,军人,干部,工人,知识分子,其他)", "昵称", "手机号"));

        Long tenantId = SecurityUtils.getUser().getTenantId();
        SysTenant tenant = tenantService.getById(tenantId);
        // , "邮箱", "部门名称", "岗位名称", "角色", "锁定标记(0:正常,9:已锁定)"
        if (tenant.getOrgType().equalsIgnoreCase("中小学")) {
            title.add("班级名称");
        } else {
            title.add("邮箱");
            title.add("部门名称");
        }

        if (userDTO.getUserType() != null && userDTO.getUserType() == 2) {
            title.add("来访时间");
        }

        if (tenant != null && StrUtil.isNotBlank(tenant.getUserFields())) {
            JSONArray jsonArray = JSON.parseArray(tenant.getUserFields());
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                if (jsonObject.getBoolean("stateData")) {
                    String filedName = jsonObject.getString("fieldName");
                    if (filedName.contains("独生子女")) {
                        title.add("独生子女(是,否)");
                    } else if (filedName.contains("陪伴")) {
                        title.add("陪伴情况(父母一方陪伴,留守儿童,父母双方陪伴)");
                    } else if (filedName.contains("父母婚姻")) {
                        title.add("父母婚姻(正常,再婚,单亲,离异)");
                    } else if (filedName.contains("婚姻情况")) {
                        title.add("婚姻情况(未婚、已婚、丧偶、再婚)");
                    } else title.add(jsonObject.getString("fieldName"));
                }
            }
        }

        XSSFWorkbook workbook = new XSSFWorkbook();
        //创建工作表sheet
        XSSFSheet sheet = workbook.createSheet();
        //创建第一行
        XSSFRow row = sheet.createRow(0);
        row.setHeightInPoints(30);

        XSSFCell cell = null;
        //插入第一行的表头
        for (int i = 0; i < title.size(); i++) {
            cell = row.createCell(i);
            cell.setCellValue(title.get(i));

            XSSFCellStyle cellStyle = workbook.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
            cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
            cellStyle.setBorderTop(BorderStyle.THIN);//上边框
            cellStyle.setBorderRight(BorderStyle.THIN);//右边框
            cellStyle.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index);
            cellStyle.setWrapText(true);
            XSSFFont font = workbook.createFont();
            font.setBold(true);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            sheet.setColumnWidth(i, 10 * 256);
        }
        List<UserExcelVO> users = userService.listUser(userDTO, ids);
        // 写入数据
        for (int i = 0; i < users.size(); i++) {
            row = sheet.createRow(i + 1);
            for (String t : title) {
                int j = ListUtils.indexOf(title, s -> StringUtils.equalsIgnoreCase(t, s));
                cell = row.createCell(j);
                // "用户名", "姓名", "年龄", "学历(小学,初中,高中,中专,大专,本科,硕士,博士)", "性别(男,女,未知)", "职业(教师,公务员,企业员工,学生,家长,农民,军人,干部,工人,知识分子,其他)", "昵称", "手机号", "邮箱", "部门名称", "岗位名称", "角色", "锁定标记(0:正常,9:已锁定)"));
                if (StringUtils.equalsIgnoreCase(t, "用户名")) {
                    cell.setCellValue(users.get(i).getUsername());
                } else if (StringUtils.equalsIgnoreCase(t, "姓名")) {
                    cell.setCellValue(users.get(i).getName());
                } else if (StringUtils.equalsIgnoreCase(t, "年龄")) {
                    cell.setCellValue(users.get(i).getAge());
                } else if (StringUtils.equalsIgnoreCase(t, "学历(小学,初中,高中,中专,大专,本科,硕士,博士)")) {
                    cell.setCellValue(users.get(i).getEdu());
                } else if (StringUtils.equalsIgnoreCase(t, "性别(男,女,未知)")) {
                    cell.setCellValue(users.get(i).getSex());
                } else if (StringUtils.equalsIgnoreCase(t, "职业(教师,公务员,企业员工,学生,家长,农民,军人,干部,工人,知识分子,其他)")) {
                    cell.setCellValue(users.get(i).getWork());
                } else if (StringUtils.equalsIgnoreCase(t, "昵称")) {
                    cell.setCellValue(users.get(i).getNickname());
                } else if (StringUtils.equalsIgnoreCase(t, "手机号")) {
                    cell.setCellValue(users.get(i).getPhone());
                } else if (StringUtils.equalsIgnoreCase(t, "邮箱")) {
                    cell.setCellValue(users.get(i).getEmail());
                } else if (StringUtils.equalsIgnoreCase(t, "部门名称")) {
                    cell.setCellValue(users.get(i).getDeptName());
                } else if (StringUtils.equalsIgnoreCase(t, "岗位名称")) {
                    cell.setCellValue(users.get(i).getDeptName());
                } else if (StringUtils.equalsIgnoreCase(t, "角色")) {
//                    cell.setCellValue(users.get(i).getRoleNameList());
                } else if (StringUtils.equalsIgnoreCase(t, "锁定标记(0:正常,9:已锁定)")) {
//                    cell.setCellValue(users.get(i).getLockFlag());
                } else if (StringUtils.equalsIgnoreCase(t, "独生子女(是,否)")) {
                    cell.setCellValue(users.get(i).getOneChild());
                } else if (StringUtils.equalsIgnoreCase(t, "陪伴情况(父母一方陪伴,留守儿童,父母双方陪伴)")) {
                    cell.setCellValue(users.get(i).getPartnerStatus());
                } else if (StringUtils.equalsIgnoreCase(t, "父母婚姻(正常,再婚,单亲,离异)")) {
                    cell.setCellValue(users.get(i).getParentMarriage());
                } else if (StringUtils.equalsIgnoreCase(t, "婚姻情况(未婚、已婚、丧偶、再婚)")) {
                    cell.setCellValue(users.get(i).getMarriage());
                } else if (StringUtils.equalsIgnoreCase(t, "班级名称")) {
                    cell.setCellValue(users.get(i).getDeptName());
                } else if (StringUtils.equalsIgnoreCase(t, "来访时间")) {
                    cell.setCellValue(DateUtil.format(users.get(i).getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
                } else {
                    cell.setCellValue("");
                }
            }
        }

        workbook.write(response.getOutputStream());
    }
}
